import sys
sys.path.append("..")
import pyrtl
from  pyrtl import GPUSim
import or1200_definitions
from or1200_rfram_generic import Or1200RframGeneric_wire

dw = or1200_definitions.OR1200_OPERAND_WIDTH
aw = or1200_definitions.OR1200_OPERAND_WIDTH

class Or1200Rf(object):
    def __init__(self):
        # self.clk = pyrtl.Input(bitwidth=1, name='clk')
        self.rst = pyrtl.Input(bitwidth=1, name='rf_rst')

        # Write i/f
        self.supv = pyrtl.Input(bitwidth=1, name='rf_supv')
        self.wb_freeze = pyrtl.Input(bitwidth=1, name='rf_wb_freeze')
        self.addrw = pyrtl.Input(bitwidth=aw, name='rf_addrw')
        self.dataw = pyrtl.Input(bitwidth=dw, name='rf_dataw')
        self.we = pyrtl.Input(bitwidth=1, name='rf_we')
        self.flushpipe = pyrtl.Input(bitwidth=1, name='rf_flushpipe')

        # Read i/f
        self.id_freeze = pyrtl.Input(bitwidth=1, name='rf_id_freeze')
        self.addra = pyrtl.Input(bitwidth=aw, name='rf_addra')
        self.addrb = pyrtl.Input(bitwidth=aw, name='rf_addrb')
        self.dataa = pyrtl.Output(bitwidth=aw,name='dataa')
        self.datab = pyrtl.Output(bitwidth=aw,name='datab')
        self.rda = pyrtl.Input(bitwidth=1, name='rf_rda')
        self.rdb = pyrtl.Input(bitwidth=1, name='rf_rdb')

        # SPR access for debugging purposes
        self.spr_cs = pyrtl.Input(bitwidth=1, name='rf_spr_cs')
        self.spr_write = pyrtl.Input(bitwidth=1, name='rf_spr_write')
        self.spr_addr = pyrtl.Input(bitwidth=32, name='rf_spr_addr')
        self.spr_dat_i = pyrtl.Input(bitwidth=32, name='rf_spr_dat_i')
        self.spr_dat_o = pyrtl.Output(bitwidth=32, name='rf_spr_dat_o')

        # Internal wires and regs
        self.from_rfa = pyrtl.WireVector(bitwidth=dw)
        self.from_rfb = pyrtl.WireVector(bitwidth=dw)

        self.dataa_saved = pyrtl.WireVector(bitwidth=dw+1)

        self.datab_saved = pyrtl.WireVector(bitwidth=dw+1)

        self.rf_we = pyrtl.WireVector(bitwidth=1)

        self.spr_valid = pyrtl.WireVector(bitwidth=1)
        self.rf_ena = pyrtl.WireVector(bitwidth=1)
        self.rf_enb = pyrtl.WireVector(bitwidth=1)
        self.rf_we_allow = pyrtl.WireVector(bitwidth=1)


        # SPR access is valid when spr_cs is asserted and
        # SPR address matches GPR addresses
        self.spr_valid |= self.spr_cs & (self.spr_addr[5:11] == or1200_definitions.OR1200_SPR_RF)

        # SPR data output is always from RF A
        self.spr_dat_o <<= self.from_rfa

        # Operand A comes from RF or from saved A register
        # self.dataa <<= self.dataa_saved[:] if self.dataa_saved[32] else self.from_rfa
        self.dataa <<= pyrtl.select(self.dataa_saved[32],self.dataa_saved[:],self.from_rfa)

        # Operand B comes from RF or from saved B register
        # self.datab = self.datab_saved[:] if self.datab_saved[32] else self.from_rfb
        self.datab <<= pyrtl.select(self.datab_saved[32], self.datab_saved[:], self.from_rfb)

        # RF A read address is either from SPRS or normal from CPU control
        # self.rf_addra = self.spr_addr[0:5] if (self.spr_valid & (not self.spr_write)) else self.addra
        #self.rf_addra <<= pyrtl.select(self.spr_valid.__rand__(~self.spr_write), self.spr_addr[0:5], self.addra)

        # RF write address is either from SPRS or normal from CPU control
        # self.rf_addrw = self.spr_addr[0:5] if (self.spr_valid & (not self.spr_write)) else self.addrw
        # self.rf_addrw <<= pyrtl.select(self.spr_valid.__rand__(~self.spr_write), self.spr_addr[0:5], self.addrw)

        # RF write data is either from SPRS or normal from CPU datapath
        # self.rf_dataw = self.spr_dat_i if (self.spr_valid & (not self.spr_write)) else self.dataw
        #self.rf_dataw <<= pyrtl.select(self.spr_valid.__rand__(~self.spr_write), self.spr_dat_i, self.dataw)
        self.rf_we <<= ((self.spr_valid & self.spr_write) | (self.we & (~self.wb_freeze))) \
                     & self.rf_we_allow & (self.supv | (self.addrw))

        # CS RF A asserted when instruction reads operand A and ID stage
        # is not stalled
        self.rf_ena <<= self.rda & (self.id_freeze) | self.spr_valid

        # CS RF B asserted when instruction reads operand B and ID stage
        # is not stalled
        self.rf_enb <<= self.rdb & (self.id_freeze) | self.spr_valid
        # initialize all the parts
        rfWriteEnable = RfWriteEnable()
        storeOperandA = StoreOperandA()
        storeOperandB = StoreOperandB()

        rframgeneric = Or1200RframGeneric_wire()
        rframgeneric.rst <<= self.rst
        rframgeneric.ce_a <<= self.rf_ena
        rframgeneric.addr_a <<= self.addra
        self.from_rfa <<= rframgeneric.do_a
        rframgeneric.ce_b <<= self.rf_enb
        rframgeneric.addr_b <<= self.addrb
        self.from_rfb <<= rframgeneric.do_b
        rframgeneric.ce_w <<= self.rf_we
        rframgeneric.we_w <<= self.rf_we
        rframgeneric.addr_w <<= self.addrw
        rframgeneric.di_w <<= self.dataw

        rfWriteEnable.rst <<= self.rst
        rfWriteEnable.wb_freeze <<= self.wb_freeze
        rfWriteEnable.flushpipe <<= self.flushpipe
        self.rf_we_allow <<= rfWriteEnable.rf_we_allow
        storeOperandA.rst <<= self.rst
        storeOperandA.id_freeze <<= self.id_freeze
        storeOperandA.from_rfa <<= self.from_rfa
        self.dataa_saved <<= storeOperandA.dataa_saved
        storeOperandB.rst <<= self.rst
        storeOperandB.id_freeze <<= self.id_freeze
        storeOperandB.from_rfb <<= self.from_rfb
        self.datab_saved <<= storeOperandB.datab_saved


class Or1200Rf_wire(object):
    def __init__(self):
        # self.clk = pyrtl.WireVector(bitwidth=1, name='clk')
        self.rst = pyrtl.WireVector(bitwidth=1, name='rf_rst')

        # Write i/f
        self.supv = pyrtl.WireVector(bitwidth=1, name='rf_rf_supv')
        self.wb_freeze = pyrtl.WireVector(bitwidth=1, name='rf_rf_wb_freeze')
        self.addrw = pyrtl.WireVector(bitwidth=aw, name='rf_rf_addrw')
        self.dataw = pyrtl.WireVector(bitwidth=dw, name='rf_rf_dataw')
        self.we = pyrtl.WireVector(bitwidth=1, name='rf_rf_we')
        self.flushpipe = pyrtl.WireVector(bitwidth=1, name='rf_rf_flushpipe')

        # Read i/f
        self.id_freeze = pyrtl.WireVector(bitwidth=1, name='rf_rf_id_freeze')
        self.addra = pyrtl.WireVector(bitwidth=aw, name='rf_rf_addra')
        self.addrb = pyrtl.WireVector(bitwidth=aw, name='rf_rf_addrb')
        self.dataa = pyrtl.WireVector(bitwidth=aw, name='rf_dataa')
        self.datab = pyrtl.WireVector(bitwidth=aw, name='rf_datab')
        self.rda = pyrtl.WireVector(bitwidth=1, name='rf_rf_rda')
        self.rdb = pyrtl.WireVector(bitwidth=1, name='rf_rf_rdb')

        # SPR access for debugging purposes
        self.spr_cs = pyrtl.WireVector(bitwidth=1, name='rf_spr_cs')
        self.spr_write = pyrtl.WireVector(bitwidth=1, name='rf_spr_write')
        self.spr_addr = pyrtl.WireVector(bitwidth=32, name='rf_spr_addr')
        self.spr_dat_i = pyrtl.WireVector(bitwidth=32, name='rf_spr_dat_i')
        self.spr_dat_o = pyrtl.WireVector(bitwidth=32, name='rf_spr_dat_o')

        # Internal wires and regs
        self.from_rfa = pyrtl.WireVector(bitwidth=dw)
        self.from_rfb = pyrtl.WireVector(bitwidth=dw)

        self.dataa_saved = pyrtl.WireVector(bitwidth=dw + 1)

        self.datab_saved = pyrtl.WireVector(bitwidth=dw + 1)

        self.rf_we = pyrtl.WireVector(bitwidth=1)

        self.spr_valid = pyrtl.WireVector(bitwidth=1)
        self.rf_ena = pyrtl.WireVector(bitwidth=1)
        self.rf_enb = pyrtl.WireVector(bitwidth=1)
        self.rf_we_allow = pyrtl.WireVector(bitwidth=1)

        # SPR access is valid when spr_cs is asserted and
        # SPR address matches GPR addresses
        self.spr_valid |= self.spr_cs & (self.spr_addr[5:11] == or1200_definitions.OR1200_SPR_RF)

        # SPR data output is always from RF A
        self.spr_dat_o <<= self.from_rfa

        # Operand A comes from RF or from saved A register
        # self.dataa <<= self.dataa_saved[:] if self.dataa_saved[32] else self.from_rfa
        self.dataa <<= pyrtl.select(self.dataa_saved[32], self.dataa_saved[:], self.from_rfa)

        # Operand B comes from RF or from saved B register
        # self.datab = self.datab_saved[:] if self.datab_saved[32] else self.from_rfb
        self.datab <<= pyrtl.select(self.datab_saved[32], self.datab_saved[:], self.from_rfb)

        # RF A read address is either from SPRS or normal from CPU control
        # self.rf_addra = self.spr_addr[0:5] if (self.spr_valid & (not self.spr_write)) else self.addra
        # self.rf_addra <<= pyrtl.select(self.spr_valid.__rand__(~self.spr_write), self.spr_addr[0:5], self.addra)

        # RF write address is either from SPRS or normal from CPU control
        # self.rf_addrw = self.spr_addr[0:5] if (self.spr_valid & (not self.spr_write)) else self.addrw
        # self.rf_addrw <<= pyrtl.select(self.spr_valid.__rand__(~self.spr_write), self.spr_addr[0:5], self.addrw)

        # RF write data is either from SPRS or normal from CPU datapath
        # self.rf_dataw = self.spr_dat_i if (self.spr_valid & (not self.spr_write)) else self.dataw
        # self.rf_dataw <<= pyrtl.select(self.spr_valid.__rand__(~self.spr_write), self.spr_dat_i, self.dataw)
        self.rf_we <<= ((self.spr_valid & self.spr_write) | (self.we & (~self.wb_freeze))) \
                       & self.rf_we_allow & (self.supv | (self.addrw))

        # CS RF A asserted when instruction reads operand A and ID stage
        # is not stalled
        self.rf_ena <<= self.rda & (self.id_freeze) | self.spr_valid

        # CS RF B asserted when instruction reads operand B and ID stage
        # is not stalled
        self.rf_enb <<= self.rdb & (self.id_freeze) | self.spr_valid
        # initialize all the parts
        rfWriteEnable = RfWriteEnable()
        storeOperandA = StoreOperandA()
        storeOperandB = StoreOperandB()

        rframgeneric = Or1200RframGeneric_wire()
        rframgeneric.rst <<= self.rst
        rframgeneric.ce_a <<= self.rf_ena
        rframgeneric.addr_a <<= self.addra
        self.from_rfa <<= rframgeneric.do_a
        rframgeneric.ce_b <<= self.rf_enb
        rframgeneric.addr_b <<= self.addrb
        self.from_rfb <<= rframgeneric.do_b
        rframgeneric.ce_w <<= self.rf_we
        rframgeneric.we_w <<= self.rf_we
        rframgeneric.addr_w <<= self.addrw
        rframgeneric.di_w <<= self.dataw

        rfWriteEnable.rst <<= self.rst
        rfWriteEnable.wb_freeze <<= self.wb_freeze
        rfWriteEnable.flushpipe <<= self.flushpipe
        self.rf_we_allow <<= rfWriteEnable.rf_we_allow
        storeOperandA.rst <<= self.rst
        storeOperandA.id_freeze <<= self.id_freeze
        storeOperandA.from_rfa <<= self.from_rfa
        self.dataa_saved <<= storeOperandA.dataa_saved
        storeOperandB.rst <<= self.rst
        storeOperandB.id_freeze <<= self.id_freeze
        storeOperandB.from_rfb <<= self.from_rfb
        self.datab_saved <<= storeOperandB.datab_saved

# RF write enable is either from SPRS or normal from CPU control
class RfWriteEnable(object):
    def __init__(self):
        # self.clk = pyrtl.Input(bitwidth=1, name='clk')
        self.rst = pyrtl.WireVector(bitwidth=1)
        self.wb_freeze = pyrtl.WireVector(bitwidth=1)
        self.flushpipe = pyrtl.WireVector(bitwidth=1)

        self.rf_we_allow = pyrtl.WireVector(bitwidth=1)

        with pyrtl.conditional_assignment:
            with self.rst:
                self.rf_we_allow |= pyrtl.Const(0b1, bitwidth=1) # #1
            with ~self.wb_freeze:
                self.rf_we_allow |= ~self.flushpipe  # #1


# Stores operand from RAF_A into temp reg when pipeline is frozen
class StoreOperandA(object):
    def __init__(self):
        # self.clk = pyrtl.Input(bitwidth=1, name='clk')
        self.rst = pyrtl.WireVector(bitwidth=1)
        self.id_freeze = pyrtl.WireVector(bitwidth=1)
        self.from_rfa = pyrtl.WireVector(bitwidth=dw)

        self.dataa_saved = pyrtl.Register(bitwidth=dw + 1)

        with pyrtl.conditional_assignment:
            with self.rst:
                self.dataa_saved.next |= pyrtl.Const(0b0, bitwidth=33)  # #1
            with (self.id_freeze & (~self.dataa_saved[32])):
                self.dataa_saved.next |= pyrtl.concat(pyrtl.Const(0b1, bitwidth=1), self.from_rfa)  # #1
            with (~self.id_freeze):
                self.dataa_saved.next |= pyrtl.Const(0b0, bitwidth=33)  # #1

# Stores operand from RF_B into temp reg when pipeline is frozen
class StoreOperandB(object):
    def __init__(self):
        # self.clk = pyrtl.Input(bitwidth=1, name='clk')
        self.rst = pyrtl.WireVector(bitwidth=1)
        self.id_freeze = pyrtl.WireVector(bitwidth=1)
        self.from_rfb = pyrtl.WireVector(bitwidth=dw)

        self.datab_saved = pyrtl.Register(bitwidth=dw + 1)

        with pyrtl.conditional_assignment:
            with self.rst:
                self.datab_saved.next |= pyrtl.Const(0b0, bitwidth=33)  # #1
            with (self.id_freeze & (~self.datab_saved[32])):
                self.datab_saved.next |= pyrtl.concat(pyrtl.Const(0b1, bitwidth=1),\
                                                 self.from_rfb)     # #1
            with (~self.id_freeze):
                self.datab_saved.next |= pyrtl.Const(0b1, bitwidth=33)   # #1


# Write port
class WritePort(object):
    def __init__(self):
        # self.clk = pyrtl.Input(bitwidth=1, name='clk')
        self.rst = pyrtl.WireVector(bitwidth=1)
        self.ce_w = pyrtl.WireVector(bitwidth=1)
        self.we_w = pyrtl.WireVector(bitwidth=1)
        self.addr_w = pyrtl.WireVector(bitwidth=aw)
        self.di_w = pyrtl.WireVector(bitwidth=dw,name='di_w')

        self.mem = pyrtl.Register(bitwidth=dw * 32)

        mem = [i for i in self.mem]
        for i in mem:
            print(i)

        with pyrtl.conditional_assignment:
            with self.rst:
                self.mem.next |= pyrtl.concat(pyrtl.Const(0b0, bitwidth=512), pyrtl.Const(0b0, bitwidth=512))
            with self.ce_w & self.we_w:
                with self.addr_w == pyrtl.Const(0, bitwidth=5):
                    mem[32 * 0: 32 * 0 + 31 + 1] = pyrtl.Const(00000000, bitwidth=32)  # #1
                    self.mem.next |= pyrtl.concat(*reversed(mem))
                with self.addr_w == pyrtl.Const(1, bitwidth=5):
                    mem[32 * 1: 32 * 1 + 31 + 1] = self.di_w  # #1
                    self.mem.next |= pyrtl.concat(*reversed(mem))
                with self.addr_w == pyrtl.Const(2, bitwidth=5):
                    mem[32 * 2: 32 * 2 + 31 + 1] = self.di_w  # #1
                    self.mem.next |= pyrtl.concat(*reversed(mem))
                with self.addr_w == pyrtl.Const(3, bitwidth=5):
                    mem[32 * 3: 32 * 3 + 31 + 1] = self.di_w  # #1
                    self.mem.next |= pyrtl.concat(*reversed(mem))
                with self.addr_w == pyrtl.Const(4, bitwidth=5):
                    mem[32 * 4: 32 * 4 + 31 + 1] = self.di_w  # #1
                    self.mem.next |= pyrtl.concat(*reversed(mem))
                with self.addr_w == pyrtl.Const(5, bitwidth=5):
                    mem[32 * 5: 32 * 5 + 31 + 1] = self.di_w  # #1
                    self.mem.next |= pyrtl.concat(*reversed(mem))
                with self.addr_w == pyrtl.Const(6, bitwidth=5):
                    mem[32 * 6: 32 * 6 + 31 + 1] = self.di_w  # #1
                    self.mem.next |= pyrtl.concat(*reversed(mem))
                with self.addr_w == pyrtl.Const(7, bitwidth=5):
                    mem[32 * 7: 32 * 7 + 31 + 1] = self.di_w  # #1
                    self.mem.next |= pyrtl.concat(*reversed(mem))
                with self.addr_w == pyrtl.Const(8, bitwidth=5):
                    mem[32 * 8: 32 * 8 + 31 + 1] = self.di_w  # #1
                    self.mem.next |= pyrtl.concat(*reversed(mem))
                with self.addr_w == pyrtl.Const(9, bitwidth=5):
                    mem[32 * 9: 32 * 931 + 1] = self.di_w  # #1
                    self.mem.next |= pyrtl.concat(*reversed(mem))
                with self.addr_w == pyrtl.Const(10, bitwidth=5):
                    mem[32 * 10: 32 * 10 + 31 + 1] = self.di_w  # #1
                    self.mem.next |= pyrtl.concat(*reversed(mem))
                with self.addr_w == pyrtl.Const(11, bitwidth=5):
                    mem[32 * 11: 32 * 11 + 31 + 1] = self.di_w  # #1
                    self.mem.next |= pyrtl.concat(*reversed(mem))
                with self.addr_w == pyrtl.Const(12, bitwidth=5):
                    mem[32 * 12: 32 * 12 + 31 + 1] = self.di_w  # #1
                    self.mem.next |= pyrtl.concat(*reversed(mem))
                with self.addr_w == pyrtl.Const(13, bitwidth=5):
                    mem[32 * 13: 32 * 13 + 31 + 1] = self.di_w  # #1
                    self.mem.next |= pyrtl.concat(*reversed(mem))
                with self.addr_w == pyrtl.Const(14, bitwidth=5):
                    mem[32 * 14: 32 * 14 + 31 + 1] = self.di_w  # #1
                    self.mem.next |= pyrtl.concat(*reversed(mem))
                with self.addr_w == pyrtl.Const(15, bitwidth=5):
                    mem[32 * 15: 32 * 15 + 31 + 1] = self.di_w  # #1
                    self.mem.next |= pyrtl.concat(*reversed(mem))
                with self.addr_w == pyrtl.Const(16, bitwidth=5):
                    mem[32 * 16: 32 * 16 + 31 + 1] = self.di_w  # #1
                    self.mem.next |= pyrtl.concat(*reversed(mem))
                with self.addr_w == pyrtl.Const(17, bitwidth=5):
                    mem[32 * 17: 32 * 17 + 31 + 1] = self.di_w  # #1
                    self.mem.next |= pyrtl.concat(*reversed(mem))
                with self.addr_w == pyrtl.Const(18, bitwidth=5):
                    mem[32 * 18: 32 * 18 + 31 + 1] = self.di_w  # #1
                    self.mem.next |= pyrtl.concat(*reversed(mem))
                with self.addr_w == pyrtl.Const(19, bitwidth=5):
                    mem[32 * 19: 32 * 19 + 31 + 1] = self.di_w  # #1
                    self.mem.next |= pyrtl.concat(*reversed(mem))
                with self.addr_w == pyrtl.Const(20, bitwidth=5):
                    mem[32 * 20: 32 * 20 + 31 + 1] = self.di_w  # #1
                    self.mem.next |= pyrtl.concat(*reversed(mem))
                with self.addr_w == pyrtl.Const(21, bitwidth=5):
                    mem[32 * 21: 32 * 21 + 31 + 1] = self.di_w  # #1
                    self.mem.next |= pyrtl.concat(*reversed(mem))
                with self.addr_w == pyrtl.Const(22, bitwidth=5):
                    mem[32 * 22: 32 * 22 + 31 + 1] = self.di_w  # #1
                    self.mem.next |= pyrtl.concat(*reversed(mem))
                with self.addr_w == pyrtl.Const(23, bitwidth=5):
                    mem[32 * 23: 32 * 23 + 31 + 1] = self.di_w  # #1
                    self.mem.next |= pyrtl.concat(*reversed(mem))
                with self.addr_w == pyrtl.Const(24, bitwidth=5):
                    mem[32 * 24: 32 * 24 + 31 + 1] = self.di_w  # #1
                    self.mem.next |= pyrtl.concat(*reversed(mem))
                with self.addr_w == pyrtl.Const(25, bitwidth=5):
                    mem[32 * 25: 32 * 25 + 31 + 1] = self.di_w  # #1
                    self.mem.next |= pyrtl.concat(*reversed(mem))
                with self.addr_w == pyrtl.Const(26, bitwidth=5):
                    mem[32 * 26: 32 * 26 + 31 + 1] = self.di_w  # #1
                    self.mem.next |= pyrtl.concat(*reversed(mem))
                with self.addr_w == pyrtl.Const(27, bitwidth=5):
                    mem[32 * 27: 32 * 27 + 31 + 1] = self.di_w  # #1
                    self.mem.next |= pyrtl.concat(*reversed(mem))
                with self.addr_w == pyrtl.Const(28, bitwidth=5):
                    mem[32 * 28: 32 * 28 + 31 + 1] = self.di_w  # #1
                    self.mem.next |= pyrtl.concat(*reversed(mem))
                with self.addr_w == pyrtl.Const(29, bitwidth=5):
                    mem[32 * 29: 32 * 29 + 31 + 1] = self.di_w  # #1
                    self.mem.next |= pyrtl.concat(*reversed(mem))
                with self.addr_w == pyrtl.Const(30, bitwidth=5):
                    mem[32 * 30: 32 * 30 + 31 + 1] = self.di_w  # #1
                    self.mem.next |= pyrtl.concat(*reversed(mem))
                with pyrtl.otherwise:
                    mem[32 * 31: 32 * 31 + 31 + 1] = self.di_w  # #1
                    self.mem.next |= pyrtl.concat(*reversed(mem))


# Read port A_1
class ReadPortA1(object):
    def __init__(self):
        # self.clk = pyrtl.WireVector(bitwidth=1, name='clk')
        self.rst = pyrtl.WireVector(bitwidth=1)
        self.ce_a = pyrtl.WireVector(bitwidth=1)
        self.addr_a = pyrtl.WireVector(bitwidth=aw)

        self.intaddr_a = pyrtl.WireVector(bitwidth=aw)

        with pyrtl.conditional_assignment:
            with self.rst:
                self.intaddr_a |= pyrtl.Const(0x0, bitwidth=5)  # #1
            with self.ce_a:
                self.intaddr_a |= self.addr_a  # #1


# Read port A
class ReadPortA2(object):
    def __init__(self):
        self.mem = pyrtl.WireVector(bitwidth=dw * 32)
        self.intaddr_a = pyrtl.WireVector(bitwidth=aw)

        self.do_a = pyrtl.WireVector(bitwidth=dw)

        with pyrtl.conditional_assignment:
            with self.intaddr_a == pyrtl.Const(0, bitwidth=5):
                self.do_a |= pyrtl.Const(0x0, bitwidth=32)
            with self.intaddr_a == pyrtl.Const(1, bitwidth=5):
                self.do_a |= self.mem[32 * 1: 32 * 1 + 31 + 1]
            with self.intaddr_a == pyrtl.Const(2, bitwidth=5):
                self.do_a |= self.mem[32 * 2: 32 * 2 + 31 + 1]
            with self.intaddr_a == pyrtl.Const(3, bitwidth=5):
                self.do_a |= self.mem[32 * 3: 32 * 3 + 31 + 1]
            with self.intaddr_a == pyrtl.Const(4, bitwidth=5):
                self.do_a |= self.mem[32 * 4: 32 * 4 + 31 + 1]
            with self.intaddr_a == pyrtl.Const(5, bitwidth=5):
                self.do_a |= self.mem[32 * 5: 32 * 5 + 31 + 1]
            with self.intaddr_a == pyrtl.Const(6, bitwidth=5):
                self.do_a |= self.mem[32 * 6: 32 * 6 + 31 + 1]
            with self.intaddr_a == pyrtl.Const(7, bitwidth=5):
                self.do_a |= self.mem[32 * 7: 32 * 7 + 31 + 1]
            with self.intaddr_a == pyrtl.Const(8, bitwidth=5):
                self.do_a |= self.mem[32 * 8: 32 * 8 + 31 + 1]
            with self.intaddr_a == pyrtl.Const(9, bitwidth=5):
                self.do_a |= self.mem[32 * 9: 32 * 9 + 31 + 1]
            with self.intaddr_a == pyrtl.Const(10, bitwidth=5):
                self.do_a |= self.mem[32 * 10: 32 * 10 + 31 + 1]
            with self.intaddr_a == pyrtl.Const(11, bitwidth=5):
                self.do_a |= self.mem[32 * 11: 32 * 11 + 31 + 1]
            with self.intaddr_a == pyrtl.Const(12, bitwidth=5):
                self.do_a |= self.mem[32 * 12: 32 * 12 + 31 + 1]
            with self.intaddr_a == pyrtl.Const(13, bitwidth=5):
                self.do_a |= self.mem[32 * 13: 32 * 13 + 31 + 1]
            with self.intaddr_a == pyrtl.Const(14, bitwidth=5):
                self.do_a |= self.mem[32 * 14: 32 * 14 + 31 + 1]
            with self.intaddr_a == pyrtl.Const(15, bitwidth=5):
                self.do_a |= self.mem[32 * 15: 32 * 15 + 31 + 1]
            with self.intaddr_a == pyrtl.Const(16, bitwidth=5):
                self.do_a |= self.mem[32 * 16: 32 * 16 + 31 + 1]
            with self.intaddr_a == pyrtl.Const(17, bitwidth=5):
                self.do_a |= self.mem[32 * 17: 32 * 17 + 31 + 1]
            with self.intaddr_a == pyrtl.Const(18, bitwidth=5):
                self.do_a |= self.mem[32 * 18: 32 * 18 + 31 + 1]
            with self.intaddr_a == pyrtl.Const(19, bitwidth=5):
                self.do_a |= self.mem[32 * 19: 32 * 19 + 31 + 1]
            with self.intaddr_a == pyrtl.Const(20, bitwidth=5):
                self.do_a |= self.mem[32 * 20: 32 * 20 + 31 + 1]
            with self.intaddr_a == pyrtl.Const(21, bitwidth=5):
                self.do_a |= self.mem[32 * 21: 32 * 21 + 31 + 1]
            with self.intaddr_a == pyrtl.Const(22, bitwidth=5):
                self.do_a |= self.mem[32 * 22: 32 * 22 + 31 + 1]
            with self.intaddr_a == pyrtl.Const(23, bitwidth=5):
                self.do_a |= self.mem[32 * 23: 32 * 23 + 31 + 1]
            with self.intaddr_a == pyrtl.Const(24, bitwidth=5):
                self.do_a |= self.mem[32 * 24: 32 * 24 + 31 + 1]
            with self.intaddr_a == pyrtl.Const(25, bitwidth=5):
                self.do_a |= self.mem[32 * 25: 32 * 25 + 31 + 1]
            with self.intaddr_a == pyrtl.Const(26, bitwidth=5):
                self.do_a |= self.mem[32 * 26: 32 * 26 + 31 + 1]
            with self.intaddr_a == pyrtl.Const(27, bitwidth=5):
                self.do_a |= self.mem[32 * 27: 32 * 27 + 31 + 1]
            with self.intaddr_a == pyrtl.Const(28, bitwidth=5):
                self.do_a |= self.mem[32 * 28: 32 * 28 + 31 + 1]
            with self.intaddr_a == pyrtl.Const(29, bitwidth=5):
                self.do_a |= self.mem[32 * 29: 32 * 29 + 31 + 1]
            with self.intaddr_a == pyrtl.Const(30, bitwidth=5):
                self.do_a |= self.mem[32 * 30: 32 * 30 + 31 + 1]
            with pyrtl.otherwise:
                self.do_a |= self.mem[32 * 31: 32 * 31 + 31 + 1]


# Read port B_1
class ReadPortB1(object):
    def __init__(self):
        # self.clk = pyrtl.WireVector(bitwidth=1, name='clk')
        self.rst = pyrtl.WireVector(bitwidth=1)
        self.ce_b = pyrtl.WireVector(bitwidth=1)
        self.addr_b = pyrtl.WireVector(bitwidth=aw)

        self.intaddr_b = pyrtl.WireVector(bitwidth=aw)

        with pyrtl.conditional_assignment:
            with self.rst:
                self.intaddr_b |= pyrtl.Const(0x0, bitwidth=5)  # #1
            with self.ce_b:
                self.intaddr_b |= self.addr_b  # #1


# Read port B
class ReadPortB2(object):
    def __init__(self):
        self.mem = pyrtl.WireVector(bitwidth=dw * 32)
        self.intaddr_b = pyrtl.WireVector(bitwidth=aw)

        self.do_b = pyrtl.WireVector(bitwidth=dw)

        with pyrtl.conditional_assignment:
            with self.intaddr_b == pyrtl.Const(0, bitwidth=5):
                self.do_b |= pyrtl.Const(0x0, bitwidth=32)
            with self.intaddr_b == pyrtl.Const(1, bitwidth=5):
                self.do_b |= self.mem[32 * 1: 32 * 1 + 31 + 1]
            with self.intaddr_b == pyrtl.Const(2, bitwidth=5):
                self.do_b |= self.mem[32 * 2: 32 * 2 + 31 + 1]
            with self.intaddr_b == pyrtl.Const(3, bitwidth=5):
                self.do_b |= self.mem[32 * 3: 32 * 3 + 31 + 1]
            with self.intaddr_b == pyrtl.Const(4, bitwidth=5):
                self.do_b |= self.mem[32 * 4: 32 * 4 + 31 + 1]
            with self.intaddr_b == pyrtl.Const(5, bitwidth=5):
                self.do_b |= self.mem[32 * 5: 32 * 5 + 31 + 1]
            with self.intaddr_b == pyrtl.Const(6, bitwidth=5):
                self.do_b |= self.mem[32 * 6: 32 * 6 + 31 + 1]
            with self.intaddr_b == pyrtl.Const(7, bitwidth=5):
                self.do_b |= self.mem[32 * 7: 32 * 7 + 31 + 1]
            with self.intaddr_b == pyrtl.Const(8, bitwidth=5):
                self.do_b |= self.mem[32 * 8: 32 * 8 + 31 + 1]
            with self.intaddr_b == pyrtl.Const(9, bitwidth=5):
                self.do_b |= self.mem[32 * 9: 32 * 9 + 31 + 1]
            with self.intaddr_b == pyrtl.Const(10, bitwidth=5):
                self.do_b |= self.mem[32 * 10: 32 * 10 + 31 + 1]
            with self.intaddr_b == pyrtl.Const(11, bitwidth=5):
                self.do_b |= self.mem[32 * 11: 32 * 11 + 31 + 1]
            with self.intaddr_b == pyrtl.Const(12, bitwidth=5):
                self.do_b |= self.mem[32 * 12: 32 * 12 + 31 + 1]
            with self.intaddr_b == pyrtl.Const(13, bitwidth=5):
                self.do_b |= self.mem[32 * 13: 32 * 13 + 31 + 1]
            with self.intaddr_b == pyrtl.Const(14, bitwidth=5):
                self.do_b |= self.mem[32 * 14: 32 * 14 + 31 + 1]
            with self.intaddr_b == pyrtl.Const(15, bitwidth=5):
                self.do_b |= self.mem[32 * 15: 32 * 15 + 31 + 1]
            with self.intaddr_b == pyrtl.Const(16, bitwidth=5):
                self.do_b |= self.mem[32 * 16: 32 * 16 + 31 + 1]
            with self.intaddr_b == pyrtl.Const(17, bitwidth=5):
                self.do_b |= self.mem[32 * 17: 32 * 17 + 31 + 1]
            with self.intaddr_b == pyrtl.Const(18, bitwidth=5):
                self.do_b |= self.mem[32 * 18: 32 * 18 + 31 + 1]
            with self.intaddr_b == pyrtl.Const(19, bitwidth=5):
                self.do_b |= self.mem[32 * 19: 32 * 19 + 31 + 1]
            with self.intaddr_b == pyrtl.Const(20, bitwidth=5):
                self.do_b |= self.mem[32 * 20: 32 * 20 + 31 + 1]
            with self.intaddr_b == pyrtl.Const(21, bitwidth=5):
                self.do_b |= self.mem[32 * 21: 32 * 21 + 31 + 1]
            with self.intaddr_b == pyrtl.Const(22, bitwidth=5):
                self.do_b |= self.mem[32 * 22: 32 * 22 + 31 + 1]
            with self.intaddr_b == pyrtl.Const(23, bitwidth=5):
                self.do_b |= self.mem[32 * 23: 32 * 23 + 31 + 1]
            with self.intaddr_b == pyrtl.Const(24, bitwidth=5):
                self.do_b |= self.mem[32 * 24: 32 * 24 + 31 + 1]
            with self.intaddr_b == pyrtl.Const(25, bitwidth=5):
                self.do_b |= self.mem[32 * 25: 32 * 25 + 31 + 1]
            with self.intaddr_b == pyrtl.Const(26, bitwidth=5):
                self.do_b |= self.mem[32 * 26: 32 * 26 + 31 + 1]
            with self.intaddr_b == pyrtl.Const(27, bitwidth=5):
                self.do_b |= self.mem[32 * 27: 32 * 27 + 31 + 1]
            with self.intaddr_b == pyrtl.Const(28, bitwidth=5):
                self.do_b |= self.mem[32 * 28: 32 * 28 + 31 + 1]
            with self.intaddr_b == pyrtl.Const(29, bitwidth=5):
                self.do_b |= self.mem[32 * 29: 32 * 29 + 31 + 1]
            with self.intaddr_b == pyrtl.Const(30, bitwidth=5):
                self.do_b |= self.mem[32 * 30: 32 * 30 + 31 + 1]
            with pyrtl.otherwise:
                self.do_b |= self.mem[32 * 31: 32 * 31 + 31 + 1]


if __name__ == '__main__':
    or1200Rf = Or1200Rf()


    com = pyrtl.CompiledSimulation()

    input_width = []
    from pyrtl.wire import Input

    IN = pyrtl.working_block().wirevector_subset(Input)
    for inn in IN:
        name = inn.name
        width = inn.bitwidth
        input_width.append([name, width])
    import random

    max_ = 0
    com_time = 0
    ess_time = 0
    num = 1
    for i in range(num):
        print(i)

        inputs_random = {}
        inputs_select = {}
        inputs_old = {}
        inputs_ = {}

        for inp in input_width:
            inputs_random[inp[0]] = []
            inputs_select[inp[0]] = []
            result = random.randint(0, 2 ** inp[1] - 1)
            inputs_old[inp[0]] = result

        for j in range(131072):
            for inp in input_width:
                result = random.randint(0, 2 ** inp[1] - 1)
                inputs_[inp[0]] = result
                inputs_random[inp[0]].append(result)
            if random.random() < 0.2:
                for name in inputs_old:
                    inputs_select[name].append(inputs_old[name])
            else:
                for name in inputs_:
                    inputs_select[name].append(inputs_[name])
                    inputs_old[name] = inputs_[name]
        time1 = com.step_multiple(inputs_select)
        print(time1)
    sim = pyrtl.GPUSim_now_loopcpugpu_dll.GPUSim('rf_cg',64,20)
    sim.make_input(inputs_select)